home *** CD-ROM | disk | FTP | other *** search
- /*
- * (C) 1992 SixxHeads Software
- * (C) 1992 Berkeley Systems Inc.
- *
- * This code is freely distributable, but credit must be given in any
- * derivative work.
- *
- * <Revision History>
- * 04/28/92 smz Created.
- * 06/13/92 smz now using fsspecs to get the info / send appleevent to FMA
- * <release 1.0>
- */
-
- #include <appleevents.h>
- #include "Utils.h"
- #include "FinderMenuInterface.h"
- #include "MenuList.h"
- #include <stdlib.h>
- #include <string.h>
- #include <stddef.h>
- #include <OSUtils.h>
- #include <Memory.h>
-
- #include "Patches.h"
-
- typedef struct {
- MenuHandle itsHandle;
- short itsOriginalID;
-
- // for hier menus
- short itsBeforeID;
-
- Boolean itsInstalled;
- } CopiedMenuRecord, **CopiedMenuHandle;
-
- typedef struct {
- OSType itsTag;
- AppleEvent itsEvent;
- Boolean itsIdle;
- Boolean itsUnused;
- short itsMenuCount;
- CopiedMenuHandle itsMenus;
- } MenuClient, **MenuClientHandle;
-
- static MenuClientHandle theMenuClients;
- static short theNextSlot = 1;
-
- #define AllocMemory(l) NewHandleSys(l)
-
- /***************************************************************************/
-
- #define CountClients() ((theMenuClients == nil)? \
- 0 : \
- (GetHandleSize(theMenuClients) / sizeof(MenuClient)))
-
- static MenuClient *GetMenuClient(reg OSType creator)
- {
- reg MenuClient *pClient;
- reg short ctClients;
- short i;
-
- if (theMenuClients == nil)
- return nil;
-
- ctClients = CountClients();
- pClient = *theMenuClients;
- while (ctClients--) {
- if (! pClient->itsUnused)
- if (pClient->itsTag == creator)
- return pClient;
- ++pClient;
- }
- return nil;
- }
-
- static MenuClient *FindEmptyClient(void)
- {
- reg MenuClient *pClient;
- reg short ctClients;
- short i;
-
- if (theMenuClients == nil)
- return nil;
-
- ctClients = CountClients();
- pClient = *theMenuClients;
- while (ctClients--) {
- if (pClient->itsUnused)
- return pClient;
- ++pClient;
- }
- return nil;
- }
-
- static void DeleteCopiedMenus(MenuClient *pClient)
- {
- reg CopiedMenuRecord *pMenu;
- reg short i;
- OSErr err;
-
- if (pClient == nil)
- return;
-
- if (pClient->itsMenus == nil)
- return;
-
- pMenu = *pClient->itsMenus;
-
- for (i = 0; i < pClient->itsMenuCount; i++, pMenu++) {
- #ifdef DEBUG
- if (pMenu->itsInstalled)
- DebugStr("\pdanger! that menus installed!");
- #endif
-
- DisposeHandle(pMenu->itsHandle);
- }
-
- pClient->itsMenuCount = 0;
- DisposeHandle(pClient->itsMenus);
- pClient->itsMenus = nil;
- }
-
- static void EmptyClient(MenuClient *pClient)
- {
- DeleteCopiedMenus(pClient);
- pClient->itsUnused = true;
- pClient->itsTag = 0;
- }
-
- /***************************************************************************/
-
- static OSErr PtrToHandSys(void* p, Handle* dest, reg unsigned short len)
- {
- reg Handle h = AllocMemory(len);
- if (h == nil)
- return MemError();
- BlockMove(p, *h, len);
- *dest = h;
- return noErr;
- }
-
- short DoInit(OSType creator)
- {
- MenuClient newClient;
- OSErr err;
- Boolean needAppend = false;
- reg MenuClient *pNewClient;
-
- if (GetMenuClient(creator) != nil)
- return eIDAlreadyInstalled;
-
- if ((pNewClient = FindEmptyClient()) == nil) {
- pNewClient = &newClient;
- needAppend = true;
- }
- pNewClient->itsTag = creator;
- pNewClient->itsMenus = nil;
- pNewClient->itsMenuCount = 0;
- pNewClient->itsIdle = true;
- pNewClient->itsUnused = false;
-
- if (! needAppend)
- err = noErr;
- else {
- if (theMenuClients == nil)
- err = PtrToHandSys(pNewClient, (Handle*) &theMenuClients, sizeof(MenuClient));
- else
- err = PtrAndHand(pNewClient, theMenuClients, sizeof(MenuClient));
- }
-
- if (err == noErr) {
- reg short rval = theNextSlot;
- theNextSlot += 64; // REMINDSMZ: what is the maximum allowable # of menus? of clients?
- return rval;
- } else {
- return eOutOfMemoryError;
- }
- }
-
- Boolean DoAppend(OSType creator, MenuHandle hMenu, short beforeID)
- {
- CopiedMenuRecord copiedMenu;
- MenuClient *pClient;
- static short negativeValue = -32000;
-
- HLock(theMenuClients);
-
- pClient = GetMenuClient(creator);
-
- if (pClient != nil) {
- OSErr err;
-
- copiedMenu.itsOriginalID = (**hMenu).menuID;
- copiedMenu.itsBeforeID = beforeID;
- copiedMenu.itsInstalled = false;
- copiedMenu.itsHandle = (MenuHandle) CopyToSystemHeap((Handle) hMenu);
- #if 0
- if (beforeID != -1)
- (**copiedMenu.itsHandle).menuID = negativeValue++;
- #endif
- if (copiedMenu.itsHandle != nil) {
- if (pClient->itsMenus == nil)
- err = PtrToHandSys(&copiedMenu, (Handle*)&pClient->itsMenus, sizeof(copiedMenu));
- else
- err = PtrAndHand(&copiedMenu, pClient->itsMenus, sizeof(copiedMenu));
-
- if (err == noErr)
- pClient->itsMenuCount++;
- }
- }
-
- HUnlock(theMenuClients);
-
- return true;
- }
-
- Boolean DoDelete(OSType creator)
- {
- if (theMenuClients == nil)
- return false;
-
- DeleteCopiedMenus(GetMenuClient(creator));
-
- return true;
- }
-
- Boolean DoRemove(OSType creator)
- {
- reg MenuClient *pClient;
- reg short ctClients;
- short i;
-
- if (theMenuClients == nil)
- return false;
-
- if (! DoDelete(creator))
- return false;
-
- ctClients = CountClients();
- pClient = *theMenuClients;
- for (i = 0; i < ctClients; i++, pClient++) {
- if ((! pClient->itsUnused) && (pClient->itsTag == creator)) {
- EmptyClient(pClient);
- return true;
- }
- }
- return false;
- }
-
- Boolean DoClientDone(OSType creator)
- {
- reg MenuClient *pClient = GetMenuClient(creator);
- pClient->itsIdle = true;
- return false;
- }
-
- /***************************************************************************/
-
- void InsertAllMenus(Boolean forShow)
- {
- reg MenuClient *pClient;
- reg short ctClients;
- reg short i;
-
- if (theMenuClients == nil)
- return;
-
- HLock(theMenuClients);
-
- ctClients = CountClients();
- pClient = *theMenuClients;
- for (i = 0; i < ctClients; i++, pClient++) {
- reg short ctMenus;
- reg short j;
- reg CopiedMenuRecord *pMenu;
-
- if (pClient->itsUnused || (pClient->itsMenus == nil))
- continue;
-
- HLock(pClient->itsMenus);
-
- pMenu = *pClient->itsMenus;
- for (j = 0; j < pClient->itsMenuCount; j++, ++pMenu) {
- if (pMenu->itsInstalled)
- continue;
-
- if (forShow && pMenu->itsBeforeID == -1)
- continue;
-
- if (pClient->itsIdle) {
- EnableItem(pMenu->itsHandle, 0);
- } else {
- DisableItem(pMenu->itsHandle, 0);
- }
-
- InsertMenu(pMenu->itsHandle, pMenu->itsBeforeID);
-
- pMenu->itsInstalled = true;
- }
-
- HUnlock(pClient->itsMenus);
- }
-
- HUnlock(theMenuClients);
- }
-
- void RemoveAllMenus(Boolean forShow)
- {
- reg MenuClient *pClient;
- reg short ctClients;
- reg short i;
-
- if (theMenuClients == nil)
- return;
-
- HLock(theMenuClients);
-
- ctClients = CountClients();
- pClient = *theMenuClients;
- for (i = 0; i < ctClients; i++, ++pClient) {
- reg short ctMenus;
- reg short j;
- reg CopiedMenuRecord *pMenu;
-
- if (pClient->itsUnused || pClient->itsMenus == nil)
- continue;
-
- HLock(pClient->itsMenus);
-
- pMenu = *pClient->itsMenus;
- for (j = 0; j < pClient->itsMenuCount; j++, ++pMenu) {
- if (! pMenu->itsInstalled)
- continue;
-
- if (forShow && pMenu->itsBeforeID == -1)
- continue;
-
- pMenu->itsInstalled = false;
- DeleteMenu(pMenu->itsOriginalID);
- }
-
- HUnlock(pClient->itsMenus);
- }
-
- HUnlock(theMenuClients);
- }
-
- /***************************************************************************/
-
- Boolean OwnedMenuHit(unsigned long result, OSType *creator, AEDescList *descList)
- {
- reg MenuClient *pClient;
- reg short ctClients;
- reg short menuID = result >> 16;
-
- if (theMenuClients == nil)
- return false;
-
- ctClients = CountClients();
- pClient = *theMenuClients;
-
- while (ctClients--) {
- reg short ctMenus;
- reg short i;
- reg CopiedMenuRecord *pMenu;
-
- if (pClient->itsUnused || (pClient->itsMenus == nil))
- continue;
-
- pMenu = *pClient->itsMenus;
-
- for (i = 0; i < pClient->itsMenuCount; i++, ++pMenu) {
- if ((**pMenu->itsHandle).menuID == menuID) {
- *creator = pClient->itsTag;
- return NewHitList(pClient->itsTag, pMenu->itsOriginalID, result & 0xffff, descList);
- }
- }
-
- ++pClient;
- }
-
- return false;
- }
-
- /***************************************************************************/
- #if 0
- pascal short waitProc(ev, sleep, mousergn)
- EventRecord *ev;
- long *sleep;
- RgnHandle *mousergn;
- {
-
- return (0); /*keep waiting*/
- } /*IACwaitroutine*/
-
- #endif
-
- #if 0
-
- //sample code for FMA
- \
- <AppleEvents.h>
-
- pascal OSErr handleMenuHitEvent (AppleEvent *event, AppleEvent *reply, long refcon)
- {
- AppleEvent evSend, reply2;
-
- AESuspendTheCurrentEvent (event);
-
- AEGetKeyPtr (evINIT, 'flis', &pathDesc); //gets list from INIT
-
- AEGetKeyDesc (evINIT, 'flis', &pathDesc); //gets list from INIT
-
- AEGetKeyDesc (evINIT, 'flis', &pathDesc); //gets list from INIT
-
- ShareMenuHit (...);
-
- AESetTheCurrentEvent (event); //needed?
-
- AEResumeTheCurrentEvent (event, reply, kAENoDispatch, refcon);
-
-
-
- AEGetKeyDesc (evINIT, 'flis', &pathDesc); //gets list from INIT
-
- err = AEPutParamDesc(reply, '----', &pathDesc); //returns list to Frontier
-
-
- void convert (MenuHitRecord *mr, AppleEvent *ev)
- {
- AEAddressDesc adr;
- OSErr err;
- AEDesc pathdesc;
- short i;
-
- err = AECreateDesc(typeApplSignature, &creator, sizeof(OSType), &adr);
-
- err = AECreateAppleEvent (cGetFinderMenuProc, finderMenuHitEvent, &adr,
- kAutoGenerateReturnID, kAnyTransactionID, ev);
-
- AEDisposeDesc (&adr);
-
- err = AEPutKeyPtr (ev, 'mnid', typeShortInteger, &mr->itsMenuID, sizeof (short));
-
- err = AEPutKeyPtr (ev, 'mnit', typeShortInteger, &mr->itsItem, sizeof (short));
-
- pathDesc.descriptorType = 'TEXT';
- for (i = (**cachedHitHandle).itsFileCount - 1; i >= 0 && err == noErr; i--) {
- Handle hName = (**cachedHitHandle).itsFileNames[i];
- if (hName) {
- pathDesc.dataHandle = hName;
- err = AEPutDesc(&resultList, 0, &pathDesc);
- }
- }
-
-
- if (err == noErr)
- err = AEPutKeyParamDesc(ev, 'flis', &resultList);
-
- AEDisposeDesc (&resultList);
-
- /****.......*/
-
- AppleEvent event, reply;
-
- //build as above during collect sequence...
-
- AESend(&event, &reply, kAENoReply, kAEHighPriority, kNoTimeOut, nil, nil);
-
- AEDisposeDesc(&event);
-
- AEDisposeDesc(&reply);
- }
- #endif
-
- void SendCancelledEvent(OSType creator)
- {
- reg MenuClient *pClient;
- AEAddressDesc adr;
- AppleEvent event, reply;
- OSErr err;
-
- err = AECreateDesc(typeApplSignature, (void*) &creator, sizeof(OSType), &adr);
-
- if (err != noErr)
- return;
-
- err = AECreateAppleEvent(cGetFinderMenuProc, cFinderCancelHitEvent, &adr,
- kAutoGenerateReturnID, kAnyTransactionID, &event);
-
- AEDisposeDesc(&adr);
-
- if (err == noErr)
- AESend(&event, &reply, kAENoReply, kAEHighPriority, kNoTimeOut, nil, nil);
-
- AEDisposeDesc(&event);
-
- AEDisposeDesc(&reply);
- }
-
- // caller is responsible for destroying hitList!
- void SendMenuHitInfo(OSType creator, AEDescList *hitList)
- {
- reg MenuClient *pClient = GetMenuClient(creator);
-
- if (pClient != nil) {
- AppleEvent event = pClient->itsEvent;
- AppleEvent reply;
-
- if (event.dataHandle == nil) {
- #ifdef DEBUG
- DebugStr("\pnil datahandle!");
- return;
- #endif
- }
-
- pClient->itsEvent.dataHandle = nil; // REMINDSMZ: by way of debugging...
- pClient->itsIdle = false;
-
- if (noErr == AEPutKeyDesc(&event, 'flis', hitList))
- AESend(&event, &reply, kAENoReply, kAEHighPriority, kNoTimeOut, nil, nil);
-
- AEDisposeDesc(&event);
-
- AEDisposeDesc(&reply);
- }
- }
-
- // this creator's info needs to get tossed - cmd-. was hit or an error occured.
- void DeleteMenuHitInfo(OSType creator)
- {
- reg MenuClient *pClient = GetMenuClient(creator);
- AppleEvent event;
-
- if (pClient == nil)
- return;
-
- if (pClient->itsIdle)
- return; // nothing to do
-
- event = pClient->itsEvent;
-
- pClient->itsEvent.dataHandle = nil; // REMINDSMZ: by way of debugging...
- pClient->itsIdle = false;
-
- if (event.dataHandle == nil) {
- #ifdef DEBUG
- DebugStr("\pnil datahandle!?");
- #endif
- return;
- }
-
- AEDisposeDesc(&event);
- }
-
- Boolean NewHitList(OSType creator, short menuID, short item, AEDescList *descList)
- {
- reg MenuClient *pClient;
- AEAddressDesc adr;
- AppleEvent event;
- OSErr err;
-
- err = AECreateList(nil, 0, false, descList);
-
- if (err != noErr)
- return false;
-
- err = AECreateDesc(typeApplSignature, (void*) &creator, sizeof(OSType), &adr);
-
- if (err != noErr)
- return false;
-
- err = AECreateAppleEvent(cGetFinderMenuProc, cFinderMenuHitEvent, &adr,
- kAutoGenerateReturnID, kAnyTransactionID, &event);
-
- AEDisposeDesc(&adr);
-
- if (err == noErr) {
- err = AEPutKeyPtr(&event, 'mnid', typeShortInteger, (void*) &menuID, sizeof(short));
-
- if (err == noErr)
- err = AEPutKeyPtr(&event, 'mnit', typeShortInteger, (void*) &item, sizeof(short));
- }
-
- if (err != noErr) {
- AEDisposeDesc(&event);
- return false;
- }
-
- pClient = GetMenuClient(creator);
-
- if (pClient == false) {
- AEDisposeDesc(&event);
- return false;
- }
- pClient->itsEvent = event;
-
- return true;
- }
-